//################################################################################
// MIT License
// Copyright (c) 2024 ZhangYihua
//
// Change Logs:
// Date           Author       Notes
// 2020-07-20     ZhangYihua   first version
//
// Description  : Single Error-bit Correction and Double Error-bit Detecttion.
//################################################################################

module sec_ded_dec #(
parameter           DW                      = 32,       // original data width, 1<=DW<=502

// the following parameters are calculated automatically
parameter           CW                      = ecc_cw_f(DW, "SEC_DED")  // the smallest redundant check width but meet DW <= 2^(CW-1) - CW
) ( 
input               [DW+CW-1:0]             cd,         // coded data
output              [DW-1:0]                od,         // original data
output              [CW-1:0]                s,          // syndrom
output                                      err,        // coded data error
output                                      sbe,        // single-bit error
output                                      dbe         // double-bit error
);

//################################################################################
// define local varialbe and localparam
//################################################################################
localparam [CW-1:0] ONE                     = 1;

wire                [DW*CW-1:0]             ep_ary;     // pattern for each single error
wire                [DW*CW-1:0]             gm_ary;     // generative matrix
reg                 [CW-1:0]                c;
reg                 [DW-1:0]                e;

//################################################################################
// main
//################################################################################

sec_ded_gep #(.DW(DW)) u_gep (.ep_ary(ep_ary), .gm_ary(gm_ary));

always@(*) begin:CHK
    integer i;

    for (i=0; i<CW; i=i+1) begin
        c[i] = ^(cd[DW-1:0] & gm_ary[i*DW+:DW]);
    end
end

assign s = c ^ cd[DW+:CW];

always@(*) begin:EP
    integer         i;

    for (i=0; i<DW; i=i+1) begin
         e[i] = (s==ep_ary[i*CW+:CW]) ? 1'b1 : 1'b0;
    end
end
assign od = cd[DW-1:0] ^ e;

assign err = |s;
assign sbe = ^s;
assign dbe = err & (~sbe);

`include "func_ecc.v"   // refer to ecc_cw_f()

//################################################################################
// ASSERTION
//################################################################################

`ifdef CBB_ASSERT_ON
// synopsys translate_off


// synopsys translate_on
`endif

endmodule
